
/* 
 * File:   LocalSource.cpp
 */
#include <dirent.h>
#include <time.h>
#include <sys/stat.h>
#include <algorithm>

#include "LocalSource.h"
#include "ActionsWithFiles.h"
#include "Account.h"
#include "File.h"
#include "Log.h"

void
LocalSource::Connect ()
{
};

std::vector<File>&
LocalSource::getLocalFiles ()
{

  Log::getInstance ()->sDebugging ("LocalSource::getLocalFiles");
  if (local_adress.adv_adr_)
   Log::getInstance ()->sDebugging ("local_adress.adv_adr"+local_adress.adv_adr);
  else
   Log::getInstance ()->sDebugging ("there is no adv_adr");


  local_files.clear ();

  if (if_synch)
    {
    Log::getInstance ()->sDebugging ("We are in the sync strategy");
      if (!local_adress.adv_adr_)
        {
          local_adress.adv_adr_ = true;
          string s (get_current_dir_name ());
          local_adress.adv_adr = s;
        };

      chdir (local_adress.adv_adr.c_str ());
      string buf = (local_adress.adv_adr + "/.emailsynch-synch");

      if ((!LocalSource::FileExists (buf)) && (synch.size () == 0))
        throw "No any idea what to do because no info about synch";

      if (!LocalSource::FileExists (buf))
        {
        //  cout << "now we would make it" << endl;
        //  cout << buf << endl;
          ofstream f;
          f.open (buf.c_str (), ios::out);
          f << synch;
          f.close ();
        };

      ifstream f;
      f.open (buf.c_str (), ios::in);
      f >> synch;

      bool if_abs = false;
      for (int i = 0; i!= local_adress.adv_adr.size (); ++i)
        if (local_adress.adv_adr[i] == '/') if_abs = true;
      if (!if_abs)
        {
          string s(get_current_dir_name());
          s+="/";
          local_adress.adv_adr = s + local_adress.adv_adr;
        }

      string path = local_adress.adv_adr;
      string target = local_adress.adv_adr;
     
      int k;
      for (int i = path.size () - 1; i >= 0; --i)
        {
          if (path[i] == '/')
            {
              k = i;
              break;
            }
        }

      path.erase (k+1, path.size () - k);
      target.erase (0, k+1);

    //  cout << path << endl;
    //  cout << target << endl;

      File file;
      loc_dir = path;

      file.action = NOTHING;
      file.full_local_path = local_adress.adv_adr;
      file.name = target;
      file.if_archive = true;
      file.if_remote = false;
      file.if_synch = true;
      file.path_only = path;

      struct stat* attr;
      attr = (struct stat*) malloc (sizeof (struct stat));
      const char* cbuf = (file.full_local_path).c_str ();
      stat (cbuf, attr);
      timespec mtime = attr->st_mtim;
      time_t t = mtime.tv_sec;
      time_t* tt = &t;
      const time_t* ttt = tt;
      struct tm* tmka;
      tmka = localtime (ttt);
      file.date.year = tmka->tm_year + 1900;
      file.date.month = tmka->tm_mon + 1;
      file.date.hour = tmka->tm_hour;
      file.date.minute = tmka->tm_min;
      file.date.day = tmka->tm_mday;
      file.synch_name = synch;


      loc_dir = path;
      local_files.push_back (file);
      return local_files;

    };




  if (local_adress.adv_adr_)
    {
      bool if_abs = false;
      for (int i = 0; i!= local_adress.adv_adr.size (); ++i)
        if (local_adress.adv_adr[i] == '/') if_abs = true;
      if (!if_abs)
        {
          string s(get_current_dir_name());
          s+="/";
          local_adress.adv_adr = s + local_adress.adv_adr;
        }
      Log::getInstance ()->sDebugging ("We are in the adv_adr strategy");
      struct stat* attr;
      attr = (struct stat*) malloc (sizeof (struct stat));
      const char* cbuf = (local_adress.adv_adr).c_str ();
      stat (cbuf, attr);
      if (S_ISDIR (attr->st_mode) != 0)
        {
          //this is directory
          loc_dir = local_adress.adv_adr;
          Log::getInstance ()->sDebugging ("LocalSource::Connect " + loc_dir);
          dir = opendir (loc_dir.c_str ());
          if_dir = true;
        }
      else
        {
          if_dir = false;
        };

        if ((if_dir) && (local_adress.adv_adr[local_adress.adv_adr.size ()-1] != '/'))
                         local_adress.adv_adr +="/";

      if ((!if_dir) || (if_archive_flag))
        {
          Log::getInstance ()->sDebugging ("We are !if_dir || if_archive_flag");
          
          if (local_adress.adv_adr[local_adress.adv_adr.size ()-1] == '/')
            {
              local_adress.adv_adr.erase (local_adress.adv_adr.size ()-1,1);
            }

          string path = local_adress.adv_adr;
          string target = local_adress.adv_adr;

          int k = -1;
          for (int i = path.size () - 1; i >= 0; --i)
            {
              if (path[i] == '/')
                {
                  k = i;
                  break;
                }
            }
          if (k == -1)
            {
              string s(get_current_dir_name());
              s+="/";
              path = s;
              target = local_adress.adv_adr;
            }
          else
            {
          path.erase (k+1, path.size () - k);
          target.erase (0, k+1);
            }

         // cout << path << endl;
         // cout << target << endl;
          loc_dir = path;

          File file;

          file.action = NOTHING;
          file.full_local_path = loc_dir + target;
          file.name = target;

          if (if_archive_flag)
            file.if_archive = true;
          else
            file.if_archive = false;

          file.if_remote = false;
          file.if_synch = false;
          file.path_only = path;

          struct stat* attr;
          attr = (struct stat*) malloc (sizeof (struct stat));
          const char* cbuf = (file.full_local_path).c_str ();
          stat (cbuf, attr);
          timespec mtime = attr->st_mtim;
          time_t t = mtime.tv_sec;
          time_t* tt = &t;
          const time_t* ttt = tt;
          struct tm* tmka;
          tmka = localtime (ttt);
          file.date.year = tmka->tm_year + 1900;
          file.date.month = tmka->tm_mon + 1;
          file.date.hour = tmka->tm_hour;
          file.date.minute = tmka->tm_min;
          file.date.day = tmka->tm_mday;
          loc_dir = path;
          local_files.push_back (file);



          return local_files;
        }

      doDir (local_adress.adv_adr);
      return local_files;
    };

    Log::getInstance ()->sDebugging ("We are in the not adv_adr strategy");
    string s(get_current_dir_name());
    s+="/";
    Log::getInstance ()->sDebugging ("Current directory "+s);
    doDir(s);
    Log::getInstance ()->sDebugging ("I'v done dir");
    return local_files;
};




void LocalSource::doDir (string& s)
{
  Log::getInstance ()->sDebugging ("LocalSource::doDir "+s);

      loc_dir = s;
      dir = opendir(loc_dir.c_str ());
      local_files.clear ();
      dirent* item;
      while (item = readdir (dir))
        {
          const char* name = item->d_name;
          string sname (name);
          if ((sname == ".") || (sname == ".."))
            continue;
          File buf;
          buf.name = sname;
          struct stat* attr;
          attr = (struct stat*) malloc (sizeof (struct stat));
          const char* cbuf = (loc_dir + sname).c_str ();
          stat (cbuf, attr);
          timespec mtime = attr->st_mtim;
          time_t t = mtime.tv_sec;
          time_t* tt = &t;
          const time_t* ttt = tt;
          struct tm* tmka;
          tmka = localtime (ttt);
          buf.date.year = tmka->tm_year + 1900;
          buf.date.month = tmka->tm_mon + 1;
          buf.date.hour = tmka->tm_hour;
          buf.date.minute = tmka->tm_min;
          buf.date.day = tmka->tm_mday;
          buf.full_local_path = loc_dir + sname;
          buf.path_only = loc_dir;
          buf.action = NOTHING;
          buf.full_local_path = loc_dir + name;
          buf.if_archive = false;
          buf.if_remote = false;
          buf.if_synch = false;

      struct stat* attr2;
      attr2 = (struct stat*) malloc (sizeof (struct stat));
      const char* cbuf2 = (buf.full_local_path).c_str ();
      stat (cbuf2, attr2);
      if (S_ISDIR (attr2->st_mode) != 0)
        {
          //this is directory
          
          buf.if_archive = true;
         
        }

          local_files.push_back (buf);
        };
      closedir (dir);
};





void
LocalSource::preCleaning (std::vector<File>& local_files_)
{
  Log::getInstance ()->sDebugging ("LocalSource::setDeletedFiles");
  for (int i = 0; i != local_files_.size (); ++i)
    if (local_files_.at (i).action == REMOVE)
      {
        Log::getInstance ()->sDebugging ("\t\t" + local_files_[i].name);
        const char* c = (local_files_[i].full_local_path).c_str ();
        remove (c);
      };
};

void LocalSource::preArchivingStuff (std::vector<File>& local_files_, std::vector<File>& remote_files_)
{
  Log::getInstance ()->sDebugging ("preArchivingStaff");

  if (if_archive_flag)
    Log::getInstance ()->sDebugging ("if_archiving flag is set");
  else
    Log::getInstance ()->sDebugging ("if archiving flag is not set");

 // cout << local_files_.at (0).action << endl;
  
  for (int i = 0 ; i != local_files_.size (); ++i)
    {
      if ((local_files_.at (i).action == SEND) && ((if_archive_flag) || (local_files_.at (i).if_archive)))
        {
          File& file_ = local_files_[i];
          chdir(local_files_.at (i).path_only.c_str ());
          string buf = file_.full_local_path;
          file_.full_local_path = file_.full_local_path+".tgz";
          Log::getInstance()->sDebugging("\t\tarchiveFileBeforeSent");
          Log::getInstance()->sDebugging("\t\tNew full local path "+file_.full_local_path);
          string s = ("tar -czf "+file_.name+".tgz "+file_.name);//+" 2> /dev/null");
          system(s.c_str());
        };
    }

};
void LocalSource::postArchivingStuff (std::vector<File>& local_files_, std::vector<File>& remote_files_)
{
  Log::getInstance ()->sDebugging ("postArchivingStaff");
  for (int i = 0 ; i != local_files_.size (); ++i)
    {
      if ((local_files_.at (i).action == SEND) && (local_files_.at (i).if_archive))
        {
          remove(local_files_.at (i).full_local_path.c_str ());
        };
    }
  
  for (int i = 0; i != remote_files_.size (); ++i)
    {
     
      if ((remote_files_[i].action == RECEIVE) && (remote_files_[i].if_archive))
        {
        File& file_ = remote_files_[i];
        Log::getInstance()->sDebugging("\t\tarchivefileAfterReceive");
        Log::getInstance()->sDebugging("\t\tfile_.full_local_path"+file_.full_local_path);
        chdir(file_.path_only.c_str ());
        Log::getInstance()->sDebugging("path only "+file_.path_only);
        Log::getInstance()->sDebugging("tar xzf "+file_.name);
        Log::getInstance()->sDebugging("");
        string s = ("tar xzf "+file_.name);
        system(s.c_str ());
        }

    }
};

